﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Playlist.cs" company="Jens Horstmann">
//   Copyright (c) Jens Horstmann. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace MiniMusicPlayer.Classes
{
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.IO;

    /// <summary>
    /// The playlist mode.
    /// </summary>
    public enum PlaylistMode
    {
        /// <summary>
        /// The loop.
        /// </summary>
        Loop, 

        /// <summary>
        /// The random.
        /// </summary>
        Random, 

        /// <summary>
        /// The single.
        /// </summary>
        Single
    }

    /// <summary>
    /// The playlist.
    /// </summary>
    public class Playlist
    {
        /// <summary>
        /// The playlist mode.
        /// </summary>
        private PlaylistMode playlistMode;

        /// <summary>
        /// Initializes a new instance of the <see cref="Playlist"/> class.
        /// </summary>
        public Playlist()
        {
            this.Songs = new ObservableCollection<Song>();
            this.ShuffledSongs = this.Songs;
            this.ShuffledSongs.CollectionChanged += this.PlaylistChanged;
            this.PlaylistMode = PlaylistMode.Loop;
            this.ActualSong = new ActualSong(this);
        }

        /// <summary>
        /// Gets or sets the actual song.
        /// </summary>
        public ActualSong ActualSong { get; set; }

        /// <summary>
        /// Gets a value indicating whether has songs.
        /// </summary>
        public bool HasSongs
        {
            get
            {
                return this.Songs.Count > 0;
            }
        }

        /// <summary>
        /// Gets or sets the playlist mode.
        /// </summary>
        public PlaylistMode PlaylistMode
        {
            get
            {
                return this.playlistMode;
            }

            set
            {
                this.playlistMode = value;

                if (this.PlaylistMode == PlaylistMode.Random)
                {
                    this.ShuffledSongs.Shuffle();
                }
            }
        }

        /// <summary>
        /// Gets or sets the songs.
        /// </summary>
        public ObservableCollection<Song> Songs { get; set; }

        /// <summary>
        /// Gets or sets the shuffled songs.
        /// </summary>
        public ObservableCollection<Song> ShuffledSongs { get; set; }

        /// <summary>
        /// The playlist changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void PlaylistChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
        }

        /// <summary>
        /// The add files.
        /// </summary>
        /// <param name="fileLocations">
        /// The file locations.
        /// </param>
        public void AddFiles(string[] fileLocations)
        {
            foreach (var fileLocation in fileLocations)
            {
                this.Songs.Add(new Song(new FileInfo(fileLocation)));
            }
        }

        /// <summary>
        /// The add files.
        /// </summary>
        /// <param name="files">
        /// The files.
        /// </param>
        public void AddFiles(FileInfo[] files)
        {
            foreach (var file in files)
            {
                this.Songs.Add(new Song(file));
            }
        }

        /// <summary>
        /// The add file.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        public void AddFile(Song song)
        {
            if (song != null)
            {
                this.Songs.Add(song);
            }
        }

        /// <summary>
        /// The next.
        /// </summary>
        /// <returns>
        /// The <see cref="Song"/>.
        /// </returns>
        public Song NextSong()
        {
            return this.ActualSong.NextSong();
        }

        /// <summary>
        /// The play.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        internal void Play(Song song)
        {
            this.ActualSong.SongChanged(song);
        }

        /// <summary>
        /// The previous song.
        /// </summary>
        /// <returns>
        /// The <see cref="Song"/>.
        /// </returns>
        public Song PreviousSong()
        {
            return this.ActualSong.PreviousSong();
        }

        /// <summary>
        /// The remove song.
        /// </summary>
        /// <param name="song">
        /// The song.
        /// </param>
        public void RemoveSong(Song song)
        {
            this.Songs.Remove(song);
        }

        /// <summary>
        /// The song ended.
        /// </summary>
        /// <returns>
        /// The <see cref="Song"/>.
        /// </returns>
        public Song SongEnded()
        {
            if (this.PlaylistMode == PlaylistMode.Single)
            {
                return this.ActualSong.Current;
            }

            return this.ActualSong.NextSong();
        }
    }
}